using Test

# Test transport initialization components
const REPO_ROOT = normpath(joinpath(@__DIR__, "..", "..", ".."))
const ONE_POINT_ROOT = joinpath(REPO_ROOT, "code", "one_point")

@testset "Transport Tests" begin

    @testset "FlexpartIO Header Reading" begin
        # Test reading the sample header file
        header_path = joinpath(ONE_POINT_ROOT, "fp_output", "AAA", "202003", "header_txt")

        if isfile(header_path)
            FlexpartIO = FLEXINVERT.TransportInit.FlexpartIO

            # Test header reading
            header = FlexpartIO.read_header_text(header_path)

            @test header.nxgrid == 30
            @test header.nygrid == 20
            @test header.llx ≈ 100.0
            @test header.lly ≈ 20.0
            @test header.dx ≈ 1.0
            @test header.dy ≈ 1.0
            @test header.nxshift == 0  # Sample fixture uses a regional grid
            @test header.nzgrid == 2
            @test length(header.outheight) == header.nzgrid
            @test header.outheight[1] ≈ 50.0  # First height level
            @test header.outheight[end] ≈ 50000.0  # Last height level
        else
            @warn "Test header file not found, skipping header reading tests"
        end
    end

    @testset "Transport Initialization" begin
        # Test transport system initialization
        import FLEXINVERT.TransportInit

        # Create test configuration
        files = FLEXINVERT.Settings.Files(
            path_flexpart = joinpath(ONE_POINT_ROOT, "fp_output"),
            file_recept = joinpath(ONE_POINT_ROOT, "fp_input_nest", "obs", "stnlist_detail.txt")
        )

        config = FLEXINVERT.Settings.Config(
            spec = "co2",
            datei = 20200312,
            datef = 20200313,
            w_edge_lon = 110.0,
            s_edge_lat = 30.0,
            e_edge_lon = 116.0,
            n_edge_lat = 36.0,
            xres = 0.5,
            yres = 0.5,
            nested = false,
            statres = 1.0,
            statres_hr = 24.0,
            nstep_nee_reg = 3,
            cinires = 1
        )

        domain = FLEXINVERT.CoreTypes.Domain(config)

        # Test date initialization
        date_info = TransportInit.initialize_dates(config)

        @test date_info.nday >= 1
        @test date_info.ntstate >= 1
        @test date_info.ndt >= 1
        @test date_info.juldatef >= date_info.juldatei

        # Test FLEXPART header finding (if files exist)
        if isdir(files.path_flexpart)
            try
                header_path = TransportInit.find_flexpart_header(files, config, false)
                @test isfile(header_path)
                @test occursin("header", header_path)
            catch err
                @warn "Could not find FLEXPART header for testing: $err"
            end
        end
    end

    @testset "Domain Validation" begin
        import FLEXINVERT.TransportInit

        # Create mock FLEXPART grids for testing
        grids = TransportInit.FlexpartGrids(
            nxgrid = 720,
            nygrid = 360,
            llx = -180.0,
            lly = -90.0,
            dx = 0.5,
            dy = 0.5,
            nxshift = 2,
            nzgrid = 12
        )

        # Test valid domain (should pass)
        config_valid = FLEXINVERT.Settings.Config(
            w_edge_lon = 110.0,
            s_edge_lat = 30.0,
            e_edge_lon = 116.0,
            n_edge_lat = 36.0,
            xres = 0.5,
            yres = 0.5,
            nested = false
        )
        domain_valid = FLEXINVERT.CoreTypes.Domain(config_valid)

        # This should not throw an error
        @test begin
            TransportInit.validate_domain_bounds(domain_valid, grids, config_valid)
            true
        end

        # Test invalid domain (western boundary outside FLEXPART)
        config_invalid = FLEXINVERT.Settings.Config(
            w_edge_lon = -190.0,  # Outside FLEXPART domain
            s_edge_lat = 30.0,
            e_edge_lon = 116.0,
            n_edge_lat = 36.0,
            xres = 0.5,
            yres = 0.5,
            nested = false
        )
        domain_invalid = FLEXINVERT.CoreTypes.Domain(config_invalid)

        @test_throws ErrorException TransportInit.validate_domain_bounds(domain_invalid, grids, config_invalid)

        # Test resolution mismatch
        config_res_mismatch = FLEXINVERT.Settings.Config(
            w_edge_lon = 110.0,
            s_edge_lat = 30.0,
            e_edge_lon = 116.0,
            n_edge_lat = 36.0,
            xres = 1.0,  # Different from FLEXPART's 0.5°
            yres = 0.5,
            nested = false
        )
        domain_res_mismatch = FLEXINVERT.CoreTypes.Domain(config_res_mismatch)

        @test_throws ErrorException TransportInit.validate_domain_bounds(domain_res_mismatch, grids, config_res_mismatch)
    end

    @testset "Integration Test" begin
        # Test the full run function with transport initialization
        if isdir(ONE_POINT_ROOT)
            settings_files = joinpath(ONE_POINT_ROOT, "run_flexinvert1", "SETTINGS_co2_nest_files.local")
            settings_config = joinpath(ONE_POINT_ROOT, "run_flexinvert1", "SETTINGS_co2_nest_config.local")

            if isfile(settings_files) && isfile(settings_config)
                result = cd(REPO_ROOT) do
                    FLEXINVERT.run(settings_files, settings_config)
                end
                @test result isa NamedTuple

                # Check that transport information is included
                @test haskey(result, :grids) || haskey(result, :date_info)

                # If transport initialization succeeded, check the results
                if result.grids !== nothing
                    @test result.grids.nxgrid > 0
                    @test result.grids.nygrid > 0
                    @test result.grids.dx > 0
                    @test result.grids.dy > 0
                end

                if result.date_info !== nothing
                    @test result.date_info.nday > 0
                    @test result.date_info.ntstate > 0
                end
            else
                @warn "Test configuration files not found, skipping integration test"
            end
        else
            @warn "Test data directory not found, skipping integration test"
        end
    end

end
